package com.hxk.analysis

/**
  * 解析的日志包含9个字段
  * 64.242.88.10 - - [07/Mar/2004:23:09:07 -0800] "GET /twiki/bin/view/TWiki/AlWilliams?rev=1.1 HTTP/1.1" 200 3697
  * @param ipAddress 客户端IP 如，64.242.88.10 或 calcite.rhyolite.com
  * @param clientIdentd 客户端唯一标识
  * @param userId 用户ID
  * @param dateTime 访问时间 [07/Mar/2004:23:09:07 -0800] ==》 07/Mar/2004:23:09:07
  * @param method 访问方法 如。GET
  * @param endpoint 访问的URL中后面的路径 如，/twiki/bin/view/TWiki/AlWilliams?rev=1.1
  * @param protocol 访问的协议 ，如，HTTP/1.1
  * @param responseCode 访问响应编码， 比如，200表示响应成功，401表示未授权
  * @param contentSize 访问的内容大小，3697KB
  */
case class ApacheAccessLog(ipAddress: String,
                           clientIdentd: String,
                           userId: String,
                           dateTime: String,
                           method: String,
                           endpoint: String,
                           protocol: String,
                           responseCode: Int,
                           contentSize: Long)

/**
  * 实现工具方法，用于解析一条一条的日志
  */
object ApacheAccessLog {
  //匹配日志中的9个字段的正则表达式：.r方法：将字符串转换为正则表达式
  //64.242.88.10 - - [07/Mar/2004:16:10:02 -0800] "GET /mailman/listinfo/hsdivision HTTP/1.1" 200 6291
  //lj1036.inktomisearch.com - - [07/Mar/2004:23:36:59 -0800] "GET /robots.txt HTTP/1.0" 200 68
  val PATTERN =
    """^(\S+) (\S+) (\S+) \[([\w:/]+\s[+\-]\d{4})\] "(\S+) (\S+) (\S+)" (\d{3}) (\d+)""".r

  /**
    * 解析日志行
    * @param log 日志的一行
    * @return case class ApacheAccessLog
    */
  def parseLogLine(log: String): Option[ApacheAccessLog] = {
    try{
      log match {
        case PATTERN(ipAddress, clientIdentd, userId, dateTime, method, endpoint, protocol, responseCode, contentSize) =>
          Some(ApacheAccessLog(ipAddress, clientIdentd, userId, dateTime, method, endpoint, protocol, responseCode.toInt, contentSize.toLong))
        case _ => throw new RuntimeException(s"""Cannot parse log line: $log""")
      }
    } catch {
      case e: RuntimeException => {
        Console.err.println(s"exception is: $e")
        None
      }
    }
  }
}
